﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using CoolCode.Caching;

namespace CoolCode {
	public static class InvokeMemberExtensions {
		private static readonly ICacheStrategy cache = new HashCacheStrategy();

		public static void SetValue<T>(this T obj, string propertyName, object propertyValue) {
			var setterDelegate = cache.Get(typeof(T).FullName + "_" + propertyName,
				() => {
					ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
					ParameterExpression value = Expression.Parameter(typeof(string), "propertyValue");
					MethodInfo setter = typeof(T).GetMethod("set_" + propertyName);
					MethodCallExpression call = Expression.Call(parameter, setter, value);
					LambdaExpression lambda = Expression.Lambda(call, parameter, value);
					var exp = lambda.Compile();
					return exp;
				});

			setterDelegate.DynamicInvoke(obj, propertyValue);
		}
	}
}
